package com.syn.synold4s.activity.google_map;

import static com.gaoyi.basemodule.baseUtil.PermissionUtils.checkLocationPermission;
import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_SATELLITE;
import static com.syn.synold4s.constants.TagCode.API_KEY;
import static com.syn.synold4s.constants.TagCode.codeDriver;
import static com.syn.synold4s.constants.TagCode.codeTowerCrane;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.location.Location;
import android.text.TextUtils;
import android.util.Log;
import androidx.activity.result.ActivityResult;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import com.gaoyi.basemodule.baseCallback.IView;
import com.gaoyi.basemodule.baseUtil.DensityUtil;
import com.gaoyi.basemodule.baseUtil.SPUtil;
import com.gaoyi.basemodule.baseUtil.ToastUtil;
import com.gaoyi.basemodule.baseUtil.WindowUtil;
import com.gaoyi.basemodule.baseconstant.SPName;
import com.gaoyi.basemodule.basedialog.LoadingDialogUtils;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.libraries.places.api.Places;
import com.syn.synold4s.R;
import com.syn.synold4s.activity.base.BaseAlertActivity;
import com.syn.synold4s.bean.dto.MapAllDeviceDto;
import com.syn.synold4s.bean.dto.ShortDto;
import com.syn.synold4s.constants.TagCode;
import com.syn.synold4s.control.ShortPopupWindow;
import com.syn.synold4s.databinding.ActivityGoogleMapBinding;
import com.syn.synold4s.util.GoogleMapUtils;
import com.syn.synold4s.vm.GoogleMapViewModel;
import java.util.List;
import java.util.Map;

public class GoogleMapActivity extends BaseAlertActivity<ActivityGoogleMapBinding, GoogleMapViewModel> implements OnMapReadyCallback, IView {

    private final String TAG = this.getClass().getSimpleName();
    private GoogleMap map;
    // 融合位置信息提供程序的入口点
    private FusedLocationProviderClient fusedLocationProviderClient;
    private LatLng defaultLocation;
    private float DEFAULT_ZOOM = 18;
    // 标记
    private String tagCode = "";
    private static Thread mThread;
    private boolean mIsShow = true;
    private boolean mIsThread = true;
    private String mMapName = "";
    private String mTagCode = "";
    private ShortPopupWindow mMapPopupWindow;
    private MapAllDeviceDto mMapAllDeviceDto = null;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_google_map;
    }

    @Override
    protected void initView() {
        WindowUtil.setWindowDecorView(this);
//        defaultLocation = new LatLng(Double.parseDouble(SPUtil.getInstance().getString(SPName.PROJ_LAT, "22.347288")),
//                Double.parseDouble(SPUtil.getInstance().getString(SPName.PROJ_LNG, "114.130737")));
////        defaultLocation = new LatLng(Double.parseDouble(SPUtil.getInstance().getString(SPName.PROJ_LAT)),
////                Double.parseDouble(SPUtil.getInstance().getString(SPName.PROJ_LNG)));
//        defaultLocation = new LatLng(Double.parseDouble(SPUtil.getInstance().getString(SPName.PROJ_LAT,"22.347288")),
//                Double.parseDouble(SPUtil.getInstance().getString(SPName.PROJ_LNG,"114.130737")));
        defaultLocation = new LatLng(Double.parseDouble(SPUtil.getInstance().getString(SPName.PROJ_LAT)),
                Double.parseDouble(SPUtil.getInstance().getString(SPName.PROJ_LNG)));
        defaultLocation = new LatLng(Double.parseDouble(SPUtil.getInstance().getString(SPName.PROJ_LAT, "22.347288")),
                Double.parseDouble(SPUtil.getInstance().getString(SPName.PROJ_LNG, "114.130737")));
        mPermissionsResult = registerForPermissionsResult();
        mTagCode = SPUtil.getInstance().getString(SPName.MAP_TAG_CODE);
        initMapType();
        initListener();
        initMap();
    }

    private void initMapType() {
        mViewModel.getMapType();
        startThread();
    }

    private void initListener() {
        mBinding.tvMapDevice.setOnClickListener(view -> showMapTypePopup());

        mBinding.cctvToolbar.setOnBackListener(this::finish);

        mBinding.btnChangeMapType.setOnClickListener(view -> {
            if (map != null) {
                // 切换图层类型
                int type = map.getMapType();
                if (type == GoogleMap.MAP_TYPE_TERRAIN) {
                    map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
                } else {
                    map.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
                }
            }
        });
    }

    private void showMapTypePopup() {
        if (mMapPopupWindow == null) {
            mMapPopupWindow = new ShortPopupWindow(mContext);
            mMapPopupWindow.setHeight(DensityUtil.dp2px(200));
            mMapPopupWindow.setAnchorView(mBinding.tvMapDevice);
            mMapPopupWindow.setOnItemClickListener((adapterView, view, i, l) -> {
                mMapPopupWindow.changeState(i);
                String[] idsAndNames = mMapPopupWindow.getSelectIdsAndNames();
                mMapName = idsAndNames[0];
                mTagCode = idsAndNames[1];
                ShortDto dto = mMapPopupWindow.getSelectDto(i);
                String code = dto.getCode();
                switch (code) {
                    case TagCode.codeWatch:
                        mViewModel.setMapWatch(dto.getSelect());
                        break;
                    case TagCode.codeLock:
                        mViewModel.setMapLock(dto.getSelect());
                        break;
                    case TagCode.code360:
                        mViewModel.setMap360(dto.getSelect());
                        break;
                    case TagCode.codeTowerCrane:
                        mViewModel.setMapTowerCrane(dto.getSelect());
                        break;
                }
                mBinding.tvMapDevice.setText(getString(R.string.device_view, mMapName));
                SPUtil.getInstance().putString(SPName.MAP_TAG_CODE, mTagCode);
//                mViewModel.clearMapDevice();
//                map.clear();
            });
            mMapPopupWindow.setOnDismissListener(() -> mBinding.tvMapDevice.setSelected(false));
        }
        mMapPopupWindow.setData(mViewModel.getMapTypes().getValue(), mTagCode);
        mBinding.tvMapDevice.setSelected(true);
        mMapPopupWindow.show();
    }

    private void handleMapType(List<ShortDto> data) {
        mViewModel.setMapWatch(false);
        mViewModel.setMapLock(false);
        mViewModel.setMap360(false);
        mViewModel.setMapTowerCrane(false);
        boolean isAll = true;
        StringBuilder names = new StringBuilder();
        if (TextUtils.isEmpty(mTagCode)) {
            mMapName = getString(R.string.all);
        } else {
            for (ShortDto dto : data) {
                if (mTagCode.contains(dto.getCode())) {
                    names.append(",").append(dto.getName());
                    switch (dto.getCode()) {
                        case TagCode.codeWatch:
                            mViewModel.setMapWatch(true);
                            break;
                        case TagCode.codeLock:
                            mViewModel.setMapLock(true);
                            break;
                        case TagCode.code360:
                            mViewModel.setMap360(true);
                            break;
                        case TagCode.codeTowerCrane:
                            mViewModel.setMapTowerCrane(true);
                            break;
                    }
                } else {
                    isAll = false;
                }
            }
            if (isAll) {
                mMapName = getString(R.string.all);
            } else {
                if (names.toString().isEmpty()) {
                    mMapName = "";
                } else {
                    mMapName = names.substring(1);
                }
            }
        }
        mBinding.tvMapDevice.setText(getString(R.string.device_view, mMapName));
    }

    private void initMap() {
        // 构造 PlacesClient
        Places.initialize(getApplicationContext(), API_KEY);
        Places.createClient(this);

        // 构造 FusedLocationProviderClient
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
        //初始化视图
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(@NonNull GoogleMap googleMap) {
        this.map = googleMap;
        if (checkLocationPermission(mContext, mPermissionsResult)) {
            configMap();
        }
    }

    /**
     * 地图配置
     */
    private void configMap() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        map.setMyLocationEnabled(true);
        map.setMapType(MAP_TYPE_SATELLITE);
        map.setOnMarkerClickListener(mapMarker -> {
            String[] str = (String[]) mapMarker.getTag();
            tagCode = str[0];
            if (codeTowerCrane.equals(tagCode) || codeDriver.equals(tagCode)) {
                mViewModel.getTowerDetails(str[1], tagCode);
            } else {
                mViewModel.getDeviceDetails(tagCode, str[1]);
            }
            return false;
        });
        // 地图UI设置
        GoogleMapUtils.uiSettings(map, true);
        // 获取当前位置
        getCurrentLocation();
        //设置默认位置
        changeMapCenter(defaultLocation);
    }

    /**
     * 获取当前位置
     */
    @SuppressLint("MissingPermission")
    private void getCurrentLocation() {
        fusedLocationProviderClient.getLastLocation()
                .addOnCompleteListener(task -> {
                    // 获取当前位置未成功
                    if (!task.isSuccessful()) {
                        Log.d(TAG, "Current location is null. Using defaults.");
                        Log.e(TAG, "Exception: " + task.getException());
                        // 设置默认位置
                        changeMapCenter(defaultLocation);
                        return;
                    }
                    Location lastKnownLocation = task.getResult();
                    if (lastKnownLocation == null) return;
                    // 移动地图到当前位置
                    //changeMapCenter(new LatLng(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()));
                });
    }

    /**
     * 改变地图中心
     */
    private void changeMapCenter(LatLng latLng) {
        // 地图中移动到经纬度处
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM));
    }

    @Override
    protected void initData() {

    }

    private void startThread() {
        Log.i(this.getClass().getSimpleName(), "mIsThread: " + mIsThread + ",mIsShow：" + mIsShow);
        if (mThread == null) {
            mThread = new Thread(() -> {
                try {
                    while (mIsThread) {
                        if (mIsShow) {
                            mViewModel.getData(mTagCode);
                        }
                        Thread.sleep(5 * 1000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        mThread.start();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mIsShow = false;
    }

    @Override
    public void onResume() {
        super.onResume();
        mIsShow = true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mThread != null) {
            mIsThread = false;
            mThread = null;
        }
    }

    @Override
    protected void initLiveData() {
        mViewModel.getResultCode().observe(this, resultCode -> {
        });

        mViewModel.getMapTypes().observe(this, this::handleMapType);

        mViewModel.getMapDeviceDetails().observe(mContext, mapAllDeviceDto -> {
            if (codeDriver.equals(tagCode)) {
                if (mapAllDeviceDto.getLocPack() != null) {
                    mMapAllDeviceDto = mapAllDeviceDto;
                    //将经纬度转换成地址
                    mViewModel.getAddressTrans(mapAllDeviceDto.getLocPack().getLat(), mapAllDeviceDto.getLocPack().getLng());
                } else {
                    GoogleMapUtils.showDialog(mContext, mapAllDeviceDto, tagCode);
                }
            } else {
                if (mapAllDeviceDto.getLat() > 0 && mapAllDeviceDto.getLng() > 0) {
                    mMapAllDeviceDto = mapAllDeviceDto;
                    //将经纬度转换成地址
                    mViewModel.getAddressTrans(mapAllDeviceDto.getLat(), mapAllDeviceDto.getLng());
                } else {
                    GoogleMapUtils.showDialog(mContext, mapAllDeviceDto, tagCode);
                }
            }
        });

        mViewModel.getAddress().observe(this, address -> {
            mMapAllDeviceDto.setAddress(address);
            GoogleMapUtils.showDialog(mContext, mMapAllDeviceDto, tagCode);
        });

        mViewModel.getMapDevice().observe(mContext, mapDevice -> {
            if (mapDevice != null && map != null) {
                map.clear();
                mapDevice.forEach(device -> GoogleMapUtils.createMarkers(map, mContext, device));
//                if (mapDevice.size() > 0 && firstPositioning) {
//                    MapAllDeviceDto device = mapDevice.get(0);
//                    changeMapCenter(new LatLng(device.getLat(), device.getLng()));
//                    firstPositioning = false;
//                }
            }
        });


    }

    @Override
    protected int initVariable() {
        return 0;
    }

    @Override
    protected void onRequestPermissionsResult(Map<String, Boolean> result) {
        if (result.values().stream().allMatch(Boolean.TRUE::equals)) {
            configMap();
        } else {
            ToastUtil.showToast(R.string.no_have_per);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, ActivityResult result) {

    }

    @Override
    public void showLoading() {
        LoadingDialogUtils.getInstance().showLoading(mContext);
    }

    @Override
    public void hideLoading() {
        LoadingDialogUtils.getInstance().dismiss();
    }
}